package ru.hh.team02.chat.client;

import ru.hh.team02.chat.messaging.Message;
import ru.hh.team02.chat.messaging.SendingQueue;
import ru.hh.team02.chat.server.ChatServer;
import ru.hh.team02.chat.utils.StringSocket;

import java.io.IOException;
import java.net.Socket;

/**
 * class fully responsible for communicating with client computer
 */
public class Client implements Runnable {

    private StringSocket socket;
    private String name = "";
    private final SendingQueue sendingQueue = new SendingQueue(1, this);
    private MessageHandler messageHandler = null;

    /**
     * Create empty client for testing purposes.
     */
    public Client(String name) {
        this.name = name;
    }

    public Client(Socket socket) {
        this.socket = new StringSocket(socket);
    }

    public String getName() {
        return name;
    }

    public String getRoom() {
        return ChatServer.REGISTRY.getClientRoom(getName());
    }

    @Override
    public void run() {
        try {
            socket.write("connected");
            ChatServer.ADMIN_LOGGER.write("New client has connected");

            registerClient();
            messageHandler = new MessageHandler(getName());
            ChatServer.MESSENGER.sendUndeliveredMessages(getName());
            sendingQueue.start();

            String message = "";
            do {
                message = socket.read();
                handleMessage(message);
            } while (!message.equals("exit"));
            ChatServer.ADMIN_LOGGER.write("Client \"" + this.name
                    + "\" has disconnected");
        } catch (IOException e) {
            ChatServer.ADMIN_LOGGER.write("client went down");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sendingQueue.terminate();
            ChatServer.REGISTRY.deleteClient(this);
            socket.close();
        }
    }

    /**
     * sends message to client. CAN BLOCK HERE!!!
     */
    public void sendMessageToClientComputer(String message) {
        try {
            socket.write(message);
        } catch (IOException e) {

        }
    }

    /**
     *
     */
    private void handleMessage(String message) {
        if (message.startsWith("change")) {
            messageHandler.changeRoom(message);
        } else if (message.startsWith("pm")) {
            messageHandler.sendPersonalMessage(message);
        } else if (message.startsWith("ok")) {
            messageHandler.markMessageInDb(message);
        } else {
            messageHandler.sendMessageToRoom(message);
        }
    }


    // ------------------------------------------ AUTHENTIFICATION METHODS

    /**
     * asks room and name. saves to registry
     */
    private void registerClient() throws IOException {
        String name = "";
        String password = "";
        do {
            socket.write("Input login");
            name = socket.read();

            socket.write("Input password");
            password = socket.read();
        } while (!(ChatServer.dbService.clientExists(name) &&
                   ChatServer.dbService.getPasswordByClientName(name).equals(password)));


        this.name = name;
        ChatServer.ADMIN_LOGGER.write("New client is \"" + this.name + "\"");
        socket.write("Ok");

        String room;
        do {
            socket.write("Room: "
                    + ChatServer.REGISTRY.getRoomNames().toString());
            socket.write("Input room name");
            room = socket.read();
        } while (!(ChatServer.REGISTRY.hasRoom(room) &&
                   ChatServer.REGISTRY.addClient(this, room)));
        ChatServer.ADMIN_LOGGER.write("New client entered in \"" + room + "\"");
        socket.write("Ok");

    }

    public boolean add(Message message) {
        return sendingQueue.add(message);

    }

}
